/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.web.ext.cmez;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.zkoss.util.resource.Labels;
import org.zkoss.zk.au.http.AuExtension;
import org.zkoss.zk.au.http.DHtmlUpdateServlet;
import org.zkoss.zk.ui.Desktop;
import org.zkoss.zk.ui.Session;
import org.zkoss.zk.ui.Sessions;
import org.zkoss.zk.ui.sys.WebAppCtrl;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

/**
 * The AU extension to upload files by ckeditor. It is based on Apache Commons
 * File Upload.
 *
 * @author jimmyshiau
 * @since 3.6.0.2
 */
public class CmezUploadExtension implements AuExtension {

    private ObjectMapper mapper = new ObjectMapper();

    public void init(DHtmlUpdateServlet servlet) throws ServletException {
    }

    public void destroy() {
    }

    public void service(HttpServletRequest request,
                        HttpServletResponse response, String pi) throws ServletException,
            IOException {
        final Session sess = Sessions.getCurrent(false);
        if (sess == null) {
            response.setIntHeader("ZK-Error", HttpServletResponse.SC_GONE);
            return;
        }
        String dtid = request.getParameter("dtid");
        String uuid = request.getParameter("uuid");
        try {
            FileItem item = parseFileItem(request);
            if (item != null) {
                final Desktop desktop = ((WebAppCtrl) sess.getWebApp())
                        .getDesktopCache(sess).getDesktopIfAny(dtid);
                CMeditor editor = (CMeditor) desktop
                        .getComponentByUuidIfAny(uuid);
                String url = editor.write(item.getName(), item.get());
                mapper.writeValue(response.getOutputStream(), new Result(1, Labels.getLabel("explorer.upload.success"), url));
            }
        } catch (Exception e) {
            mapper.writeValue(response.getOutputStream(), new Result(0, e.getMessage(), null));
        }
    }

    private FileItem parseFileItem(HttpServletRequest request) throws Exception {
        if (ServletFileUpload.isMultipartContent(request)) {

            FileItemFactory factory = new DiskFileItemFactory();
            ServletFileUpload servletFileUpload = new ServletFileUpload(factory);
            servletFileUpload.setHeaderEncoding("UTF-8");
            @SuppressWarnings("unchecked")
            List<FileItem> fileItemsList = servletFileUpload
                    .parseRequest(request);

            for (Iterator<FileItem> it = fileItemsList.iterator(); it.hasNext(); ) {
                FileItem item = it.next();
                if (!item.isFormField()) {
                    return item;
                }
            }
        }
        return null;
    }

    /*
     上传的后台只需要返回一个 JSON 数据，结构如下：
     {
        success : 0 | 1,           // 0 表示上传失败，1 表示上传成功
        message : "提示的信息，上传成功或上传失败及错误信息等。",
        url     : "图片地址"        // 上传成功时才返回
     }
     */
    static class Result {
        private int success;
        private String message;
        private String url;

        public Result(int success, String message, String url) {
            this.success = success;
            this.message = message;
            this.url = url;
        }

        public int getSuccess() {
            return success;
        }

        public String getMessage() {
            return message;
        }

        public String getUrl() {
            return url;
        }

    }
}
